package com.wewoo.log4e.core;

import com.alibaba.fastjson.JSON;
import com.wewoo.log4e.core.entity.Log;
import com.wewoo.log4e.core.entity.OperationLog;
import com.wewoo.log4e.core.exception.Log4eException;
import com.wewoo.log4e.core.executor.LogExecutor;
import com.wewoo.log4e.core.spring.boot.autoconfigure.Log4eProperties;
import com.wewoo.log4e.core.util.ReadLogUtil;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Slf4j
public class LogTemplate implements InitializingBean {
    public static final Logger LOGGER = LoggerFactory.getLogger(LogTemplate.class);
    @Setter
    private List<LogExecutor> executors;
    @Setter
    private Log4eProperties log4eProperties;
    private final Map<Class<? extends LogExecutor>, LogExecutor> executorMap = new LinkedHashMap<>();
    private LogExecutor primaryExecutor;

    @Override
    public void afterPropertiesSet() throws Exception {
        //校验配置文件必填
        Assert.hasText(log4eProperties.getLevel(), "level must be not blank");
        //将所有加载到的执行器放入本地缓存
        executors.forEach(i -> {
            executorMap.put(i.getClass(), i);
        });
        //根据配置文件匹配设置主执行器
        final Class<? extends LogExecutor> primaryExecutor = log4eProperties.getPrimaryExecutor();
        if (primaryExecutor == null) {
            this.primaryExecutor = executors.get(0);
        } else {
            this.primaryExecutor = executorMap.get(primaryExecutor);
        }
        Assert.notNull(this.primaryExecutor, "primaryExecutor must be not null");
        LOGGER.info("load current primary executor - {} ", this.primaryExecutor);
    }


    /**
     * 模板方法：根据传入的执行器类型去获取该执行器 执行
     **/
    public void writeLog(OperationLog log, Class<? extends LogExecutor> excutor) {
        //装配实际的执行器
        LogExecutor<OperationLog> logExecutor = obtainExecutor(excutor);
        LOGGER.info(String.format("use executor class: %s", logExecutor.getClass()));
        //执行aop的切面任务
        OperationLog result = null;
        try {
            result = logExecutor.writeLog(log);
        } catch (Exception e) {
            LOGGER.error("log4e error:{}", e.toString());
            throw new Log4eException(e.toString());
        }
        LOGGER.info(String.format("executor return result: %s", JSON.toJSONString(result)));
    }


    /**
     * 模板方法：根据传入的执行器类型去获取该执行器 执行
     **/
    public void writeLog(String log, Class<? extends LogExecutor> excutor) {

    }

    protected LogExecutor obtainExecutor(Class<? extends LogExecutor> clazz) {
        if (null == clazz || clazz == LogExecutor.class) {
            return primaryExecutor;
        }
        final LogExecutor lockExecutor = executorMap.get(clazz);
        Assert.notNull(lockExecutor, String.format("can not get bean type of %s", clazz));
        return lockExecutor;
    }


    public LogExecutor getPrimaryExecutor() {
        return this.primaryExecutor;
    }
}
